#include <event2/event.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/util.h>
#include <event2/event_struct.h>

#include <iostream>
#include <cstring>
#include <signal.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <sys/socket.h>

// 内存拷贝次数	1次（直接缓冲区到缓冲区）
// Callback when data is read from a client
void echo_read_cb(struct bufferevent *bev, void *ctx) {
    struct evbuffer *input = bufferevent_get_input(bev);
    struct evbuffer *output = bufferevent_get_output(bev);
    
    // Move all data from input buffer to output buffer (echo)
    evbuffer_add_buffer(output, input);
}


//2次（缓冲区→数组→缓冲区）
static void conn_readcb(struct bufferevent *bev, void *user_data) 
{ 
	printf("---calll-----%s\n",__FUNCTION__); 
	 //何时被触发？读入缓冲区有数据的时候，非底层的
	 char buf[256]={0}; 
	 size_t ret = bufferevent_read(bev, buf, sizeof(buf)); 
	 if(ret > 0){ 
		 //转为大写
		 int i; 
		 for(i = 0; i < ret ; i ++){ 
		 	buf[i] = toupper(buf[i]); 
		 } 
		 //写到 bufferevent 的输出缓冲区
	 	 bufferevent_write(bev, buf, ret); 
	 } 
}

// Callback when write operation is finished
void echo_write_cb(struct bufferevent *bev, void *ctx) {
    struct evbuffer *output = bufferevent_get_output(bev);
    
    // If output buffer is empty, we've finished writing
    if (evbuffer_get_length(output) == 0) {
        std::cout << "Flushed answer\n";
    }
}

// Callback for network events (connect, error, etc.)
void echo_event_cb(struct bufferevent *bev, short events, void *ctx) {
    if (events & BEV_EVENT_ERROR) {
        perror("Error from bufferevent");
    }
    
    if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
        bufferevent_free(bev);
    }
    printf("---call------%s----  network event %d \n",__FUNCTION__, events);
}

// Callback when a new connection is accepted
void accept_conn_cb(struct evconnlistener *listener, evutil_socket_t fd,
                    struct sockaddr *address, int socklen, void *ctx) {
    printf("---call------%s----\n",__FUNCTION__);                     
    struct event_base *base = evconnlistener_get_base(listener);
    //定义 bufferevent 事件
    struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    //设置回调函数 设置了写回调和事件产生回调
    bufferevent_setcb(bev, echo_read_cb, echo_write_cb, echo_event_cb, NULL);
    //启用读写缓冲区
    bufferevent_enable(bev, EV_READ|EV_WRITE);
}

// Callback when accepting a connection fails
void accept_error_cb(struct evconnlistener *listener, void *ctx) {
    struct event_base *base = evconnlistener_get_base(listener);
    int err = EVUTIL_SOCKET_ERROR();
    std::cerr << "Got an error %d (%s) on the listener. "
              << "Shutting down.\n" << err << evutil_socket_error_to_string(err);
    
    event_base_loopexit(base, NULL);
}
static void signal_cb(evutil_socket_t sig, short events, void *user_data) 
{ 
	 printf("---call------%s----\n",__FUNCTION__); 
	 struct event_base *base = static_cast<event_base *>(user_data); 
	 struct timeval delay = { 2, 0 };//设置延迟时间 2s
	 printf("Caught an interrupt signal; exiting cleanly in two seconds.\n"); 
	 event_base_loopexit(base, &delay);//延时 2s 退出
} 

int main() {
    struct event_base *base;         // 事件循环
    struct evconnlistener *listener; // 监听器
    struct event *signal_event;      //信号事件
    struct sockaddr_in sin;
    
    // Create a new event base (like an event loop)
    base = event_base_new();
    if (!base) {
        std::cerr << "Couldn't open event base\n";
        return 1;
    }
    
    // Clear the sockaddr structure and set up the server address
    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(9999); // Listen on port 9999
    sin.sin_addr.s_addr = htonl(0); // Listen on all interfaces
    
    // Create a listener for incoming connections
    listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
                                       LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE,
                                       -1, (struct sockaddr*)&sin, sizeof(sin));
    
    if (!listener) {
        std::cerr << "Couldn't create listener\n";
        return 1;
    }
    
    // Set up error callback for the listener
    evconnlistener_set_error_cb(listener, accept_error_cb);

    //定义信号回调事件 -SIGINT 
	 signal_event = evsignal_new(base, SIGINT, signal_cb, (void *)base); 
	 //event_add 上树 -开始监听信号事件
	 if (!signal_event || event_add(signal_event, NULL)<0) { 
		 fprintf(stderr, "Could not create/add a signal event!\n"); 
		 return 1; 
	 } 

    
    // Start the event loop
    event_base_dispatch(base);
    
    // Clean up
    evconnlistener_free(listener);
    event_base_free(base);
    
    return 0;
}